package com.jmz.apt.api.filter;

import com.google.common.collect.Sets;
import com.jmz.apt.api.Helper.ResponseHelper;
import com.jmz.apt.api.Utils.JsonSerializerUtil;
import com.jmz.apt.api.Utils.ResponseUtil;
import com.jmz.apt.api.common.AptConstant;
import com.jmz.apt.api.common.SecurityContextHolder;
import com.jmz.apt.api.configure.ExclusionUrl;
import com.jmz.apt.api.dto.impl.AdminTokenDto;
import com.jmz.apt.api.entity.dbEntity.JmzAdminResource;
import com.jmz.apt.api.enums.ResponseCode;
import com.jmz.apt.api.enums.RoleCode;
import com.jmz.apt.api.service.user.AdminUser;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

/**
 * Created by fanglexue on 2019/10/25.
 */
@Slf4j
public class AclFilter  implements Filter {

    @Autowired
    ResponseUtil responseUtil;

    @Autowired
    AdminUser adminUser;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    RedisTemplate<String, Serializable> redisTemplate;

    @Autowired
    ResponseHelper responseHelper;

    private static Set<String> exclusionUrlSet = Sets.newConcurrentHashSet();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        exclusionUrlSet=Sets.newConcurrentHashSet();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        HttpServletResponse servletResponse = (HttpServletResponse) response;
        String token = servletRequest.getHeader("token");

        String url = servletRequest.getRequestURI().substring(servletRequest.getContextPath().length());

        if (url.startsWith("/") && url.length() > 1) {
            url = url.substring(1);
        }
        if (ExclusionUrl.isInclude(url)) {
            chain.doFilter(servletRequest, servletResponse);
            return;
        }

        AdminTokenDto agent = SecurityContextHolder.getAgent();
        if (agent == null) {
            log.error("acl agent 获取失败");
            responseHelper.setResponseBCode(ResponseCode.GET_UINFO_FAILURE.getCode(),
                    ResponseCode.GET_UINFO_FAILURE.getDesc());
            responseHelper.outPut(servletResponse);
            return;
        }

        log.info(servletRequest.getServletPath());
        if (!hasUrlAcl(servletRequest.getServletPath())) {

            responseHelper.setResponseBCode(ResponseCode.NO_PERMISSION.getCode(),
                    ResponseCode.NO_PERMISSION.getDesc());
            responseHelper.outPut(servletResponse);
            return;
        }
        chain.doFilter(servletRequest, servletResponse);
        return;
    }

    private boolean isSuperAdmin(){
        AdminTokenDto agent=SecurityContextHolder.getAgent();
        if (agent.getRoleId().equals(RoleCode.ROLE_ADMIN.getType())){
            return true;
        }
        return false;
    }

    public boolean hasUrlAcl(String url) {
        if (isSuperAdmin()) {
            return true;
        }
        AdminTokenDto agent = SecurityContextHolder.getAgent();
        if (agent != null) {
            try {
                String redisRoleResourceKey = AptConstant.Redis.ROLE_PREFIX + agent.getRoleId().toString();
                if(!stringRedisTemplate.hasKey(redisRoleResourceKey).booleanValue()) {
                    return false;
                }
                String resources = stringRedisTemplate.opsForValue().get(redisRoleResourceKey);
                List<JmzAdminResource> authorities = JsonSerializerUtil.string2Obj(resources,ArrayList.class,JmzAdminResource.class);
                for (JmzAdminResource authority : authorities) {
                    if (url.contains(authority.getUrl())) {
                        return true;
                    }
                }
            }catch (NullPointerException e){
                log.info(e.getMessage());
                return false;
            }
        }
        return false;
    }

    public static Logger getLog() {
        return log;
    }


    @Override
    public void destroy() {

    }

}

